using System;
using System.IO;
using System.Web.UI.WebControls;
using System.Collections.Generic;

namespace Sex
{
    public partial class Sex : System.Web.UI.Page
    {
        const string ValueDelimiter = ",";
        /*
        const bool UseLogin = true;
        const string Password = "SEXy";
        const bool DynamicLoadTree = false;
        const bool AutocloseTree = true;
        const int ThumbDimension = 200;
        const int ThumbCols = 3;
        const int MaxLineLength = 27; // used for thumb preview of text
        const int MaxLineCount = 10; // used for thumb preview of text
        const string UrlJsHighlight = "http://alexgorbatchev.com/pub/sh/current/";

        string[] IpsAllowed = new string[]
        {
            "127.0.0.1",  // localhost
            "192.168.0.107", // host in private network
            "86.59.41.251" // public host
        };
        */
        State MyState = null;

        protected void HideAllControls()
        {
            // Title
            Label_Server.Visible = false;
            Label_ServerPath.Visible = false;
            Label_TitleItem.Visible = false;
            Label_PathItem.Visible = false;

            HideItemMenus();

            // Tree Menu
            Tree_Content.Visible = false;
            Tree_Controls.Visible = false;

            // Content
            iframe_Content.Visible = false;
            Literal_Content.Visible = false;
        }
        protected void HideItemMenus()
        {
            // Menu
            Table_TreeCommands.Visible = false;
            Menu_Directory.Visible = false;
            Menu_File.Visible = false;
            DropDownList_Template.Visible = false;
            Panel_LoginCommands.Visible = false;
        }
        public static string Untag(string Html)
        {
            return Html.Replace("<", "&lt;").Replace(">", "&gt;");
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (ViewState["OwnFile"] == null) MyState = new State();
            else MyState = new State(ViewState);
            if (MyState.UserAccepted || !MyState.UseLogin || IsIpAllowed())
            {
                if (MyState.CurrentServer == "")
                {
                    HideAllControls(); 
                    MyState.OwnFile = System.IO.Path.GetFileName(Request.ServerVariables["PATH_INFO"]).ToLower();
                    DirectoryInfo RootDir = new DirectoryInfo(Server.MapPath("~/"));
                    string RelativePath = MyState.RelativePath;
                    RelativePath = RelativePath.Replace("/", "\\");
                    if (RelativePath != "")
                    {
                        while (RelativePath.StartsWith("\\")) RelativePath = RelativePath.Substring(1);
                        while (RelativePath.EndsWith("\\")) RelativePath = RelativePath.Substring(0, RelativePath.Length-1);
                    }
                    MyState.RelativePathComponents = RelativePath.Split(new char[] { '\\' });

                    MyState.RootDirFullName += RootDir + RelativePath + "\\";
                    RootDir = new DirectoryInfo(MyState.RootDirFullName);
                    MyState.RootDirFullName = System.IO.Path.GetFullPath(MyState.RootDirFullName);

                    MyState.CurrentServer = Request.Url.Authority;
                    // if (!MyState.CurrentServer.EndsWith("/")) MyState.CurrentServer += "/";

                    // is Sex installend in a Subdirectory or virtualDirectory?
                    MyState.ApplicationPath = Request.ApplicationPath;
                    if (MyState.ApplicationPath == "/") MyState.ApplicationPath = "";

                    MyState.CurrentFile = "";
                    // Directory Tree
                    Tree_Content.Nodes.Clear();
                    TreeNode RootNode;
                    if (MyState.DynamicLoadTree)
                    {
                        RootNode = GetTreeDynamic(RootDir, null, true);
                    }
                    else
                    {
                        RootNode = GetTree(RootDir, null);
                    }
                    RootNode.Expanded = false;
                    Tree_Content.Nodes.Add(RootNode);

                    Tree_Controls.CollapseAll();
                    Tree_Content.CollapseAll();
                    MyState.SaveState(ViewState);
                }
            }
            else
            {
                HideAllControls();
                Login();
                return;
            }
            Label_Server.Visible = true;
            Label_ServerPath.Visible = true;
            Label_Server.Text = MyState.CurrentServer;
            Label_ServerPath.Text = MyState.ApplicationPath;

            Tree_Content.Visible = true;
            Tree_Controls.Visible = true;
            Table_TreeCommands.Visible = true;
        }
        TreeNode GetTree(DirectoryInfo directory, TreeNode parentNode)
        {
            if (directory == null) return null;

            // Directory Tree
            string Text = directory.Name; 
            string Value = "d" + ValueDelimiter + "0" + ValueDelimiter + directory.Name;
            string ToolTip = Value;
            TreeNode DirNode = new TreeNode(Text,Value);
            DirNode.ToolTip = ToolTip;
            DirNode.Expanded = false;

            // Subdirectories recursive
            System.IO.DirectoryInfo[] SubDirectories = directory.GetDirectories();
            for (int DirectoryCount = 0; DirectoryCount < SubDirectories.Length; DirectoryCount++)
            {
                DirNode.ChildNodes.Add(GetTree(SubDirectories[DirectoryCount], DirNode));
            }

            // Files
            System.IO.FileInfo[] Files = directory.GetFiles();
            for (int FileCount = 0; FileCount < Files.Length; FileCount++)
            {
                Text = Files[FileCount].Name;
                Value = "f" + ValueDelimiter + Files[FileCount].Length.ToString() + ValueDelimiter + Text;
                ToolTip = Value;
                TreeNode FileNode = new TreeNode(Text,Value);
                FileNode.ToolTip = ToolTip;
                DirNode.ChildNodes.Add(FileNode); 
            }
            return DirNode;
        }
        TreeNode GetTreeDynamic(DirectoryInfo directory, TreeNode parentNode, bool first)
        {
            if (directory == null) return null;
            TreeNode DirNode = new TreeNode(directory.Name, "d" + ValueDelimiter + "0" + ValueDelimiter + directory.Name);
            DirNode.Expanded = false;
            if (!first) DirNode.PopulateOnDemand = true;
            if (!first) return DirNode;
            System.IO.DirectoryInfo[] SubDirectories = directory.GetDirectories();
            for (int DirectoryCount = 0; DirectoryCount < SubDirectories.Length; DirectoryCount++)
            {
                DirNode.ChildNodes.Add(GetTreeDynamic(SubDirectories[DirectoryCount], DirNode, false));
            }
            System.IO.FileInfo[] Files = directory.GetFiles();

            for (int FileCount = 0; FileCount < Files.Length; FileCount++)
            {
                string FileName = Files[FileCount].Name;
                DirNode.ChildNodes.Add(new TreeNode(FileName, "f" + ValueDelimiter + Files[FileCount].Length.ToString() + ValueDelimiter + FileName));
            }
            return DirNode;
        }

        protected void Login()
        {
            Panel_LoginCommands.Visible = true;
            MyState.SaveState(ViewState);
        }
        bool IsIpAllowed()
        {
            string UserIp = Request.UserHostAddress;
            for (int i = 0; i < MyState.IpsAllowed.Length; i++)
            {
                if (UserIp == MyState.IpsAllowed[i])
                    return true;
            }
            return false;
        }
        protected bool IsAllowedMenuItem(MenuItem mi, List<string> li)
        {
            foreach (string v in li)
            {
                if (mi.Value == v) return true;
            }
            return false;
        }
        protected string GetRelativePathWithoutItem(string RelPath, string Item)
        {
            if (RelPath.ToLower().EndsWith(Item.ToLower()))
                return RelPath.Substring(0, RelPath.Length - Item.Length);
            else
                return RelPath;
        }
        protected void Menu_MenuItemClick(object sender, MenuEventArgs e)
        {
            Menu m = (Menu)sender;
            string SelectedValue = m.SelectedValue;
            switch (SelectedValue)
            {
                // File Commands
                case "FileInline":
                    MenuFileExecute(E_ObjectCommand.INLINE);
                    break;
                case "FileCode":
                    MenuFileExecute(E_ObjectCommand.CODE);
                    break;
                case "FileFrame":
                    MenuFileExecute(E_ObjectCommand.FRAME);
                    break;
                case "FileNewWin":
                    MenuFileExecute(E_ObjectCommand.NEWWIN);
                    break;
                case "FileEmbed":
                    MenuFileExecute(E_ObjectCommand.EMBED);
                    break;
                case "FileHex":
                    MenuFileExecute(E_ObjectCommand.HEX);
                    break;
                case "FilePermissions":
                    MenuFileExecute(E_ObjectCommand.PERMISSIONS);
                    break;
                case "FileDownload":
                    MenuFileExecute(E_ObjectCommand.DOWNLOAD);
                    break;
                case "FileSpecial":
                    MenuFileExecute(E_ObjectCommand.SPECIAL);
                    break;
                case "FileExif":
                    MenuFileExecute(E_ObjectCommand.EXIF);
                    break;
                // Directory Commands
                case "DirectoryFrame":
                    MenuDirectoryExecute(E_ObjectCommand.FRAME);
                    break;
                case "DirectoryList":
                    MenuDirectoryExecute(E_ObjectCommand.DIRECTORY);
                    break;
                case "DirectoryPermissions":
                    MenuDirectoryExecute(E_ObjectCommand.PERMISSIONS);
                    break;
                case "DirectoryThumbs":
                    MenuDirectoryExecute(E_ObjectCommand.THUMBS);
                    break;
                // Tree Commands
                case "0":
                case "1":
                case "2":
                case "3":
                case "9":
                    int Level = int.Parse(SelectedValue);
                    if (Tree_Content.Nodes.Count > 0)
                        Tree.Expand(Tree_Content.Nodes[0], Level);
                    break;
            }
            MyState.SaveState(ViewState);
        }
        protected void LinkButton_Server_Command(object sender, CommandEventArgs e)
        {
            switch (e.CommandName)
            {
                case "Login":
                    if (TextBox_Login.Text == MyState.Password)
                    {
                        MyState.UserAccepted = true;
                        MyState.SaveState(ViewState);
                        Page_Load(null, null);
                    }
                    break;
                case "Search":
                    if (TextBox_Search.Text == "")
                    {
                        Tree_Content.ShowCheckBoxes = TreeNodeTypes.None;
                    }
                    else
                    {
                        Tree_Content.ShowCheckBoxes = TreeNodeTypes.All;
                        Tree.Expand(Tree_Content.Nodes[0], 0);
                        if (!Tree.Search(Tree_Content.Nodes[0], TextBox_Search.Text))
                            Tree_Content.ShowCheckBoxes = TreeNodeTypes.None;
                    }
                    break;
            }
            MyState.SaveState(ViewState);
        }
        protected void DropDownList_Template_SelectedIndexChanged(object sender, EventArgs e)
        {
            MenuFileExecute(E_ObjectCommand.EMBED);
        }
        protected void Tree_Content_TreeNodePopulate(object sender, TreeNodeEventArgs e)
        {
            if (MyState.DynamicLoadTree) 
            {
                MyState = new State(ViewState);
                ItemInfo ii = new ItemInfo(e.Node.Value);
                string Path = Tree.Path(e.Node);
                DirectoryInfo di = new DirectoryInfo(MyState.RootDirFullName + Path);
                System.IO.DirectoryInfo[] SubDirectories = di.GetDirectories();
                for (int DirectoryCount = 0; DirectoryCount < SubDirectories.Length; DirectoryCount++)
                {
                    TreeNode tn = new TreeNode(SubDirectories[DirectoryCount].Name, "d" + ValueDelimiter + "0" + ValueDelimiter + SubDirectories[DirectoryCount].Name);
                    tn.PopulateOnDemand = true;
                    e.Node.ChildNodes.Add(tn);
                }
                System.IO.FileInfo[] Files = di.GetFiles();
                for (int FileCount = 0; FileCount < Files.Length; FileCount++)
                {
                    string FileName = Files[FileCount].Name;
                    e.Node.ChildNodes.Add(new TreeNode(FileName, "f" + ValueDelimiter + Files[FileCount].Length.ToString() + ValueDelimiter + FileName));
                }
                // MyState.SaveState(ViewState);
            }
        }
        protected void Tree_Content_TreeNodeExpanded(object sender, TreeNodeEventArgs e)
        {
            // e.Node.Selected = true;
        }
        protected void Tree_Content_SelectedNodeChanged(object sender, EventArgs e)
        {
            // Unselect the menu tree
            if (Tree_Controls.SelectedNode != null) Tree_Controls.SelectedNode.Selected = false;
            HideItemMenus();
            Table_TreeCommands.Visible = true;
            TreeNode tn = Tree_Content.SelectedNode;
            if (MyState.AutocloseTree)
            {
                Tree_Controls.CollapseAll();
                Tree_Content.CollapseAll();
                Tree.ExpandPath(tn);
            }
            // CurrentPathRel
            MyState.CurrentPathRel = Tree.Path(tn);
            if (MyState.CurrentPathRel == "") MyState.CurrentPathRel = "/";
            else if (!MyState.CurrentPathRel.StartsWith("/")) MyState.CurrentPathRel = "/" + MyState.CurrentPathRel;
            
            //  CurrentPathAbs
            MyState.CurrentPathAbs = MyState.CurrentPathRel.Replace("/","\\");
            if (MyState.CurrentPathAbs.StartsWith("\\")) MyState.CurrentPathAbs = MyState.CurrentPathAbs.Substring(1);
            MyState.CurrentPathAbs = MyState.RootDirFullName + MyState.CurrentPathAbs;

            string Extension = Path.GetExtension(MyState.CurrentPathRel).ToLower();

            Label_TitleItem.Visible = true;
            Label_PathItem.Visible = true;

            ItemInfo ii = new ItemInfo(tn.Value);
            switch (ii.type)
            {
                case E_ObjectType.DIRECTORY:
                default:

                    Menu_Directory.Visible = true;
                    MyState.CurrentFile = new DirectoryInfo(MyState.CurrentPathAbs).Name;
                    Label_PathItem.Text = GetRelativePathWithoutItem(MyState.CurrentPathRel, MyState.CurrentFile);
                    if (!Label_PathItem.Text.EndsWith("/")) Label_PathItem.Text += "/";
                    Label_PathItem.ToolTip = Label_PathItem.Text;
                    Label_TitleItem.Text = tn.Parent==null ? "" : MyState.CurrentFile;
                    MenuDirectoryExecute(E_ObjectCommand.DIRECTORY);
                    break;

                case E_ObjectType.FILE:

                    // q & d reaading word file "Access denied" on C:\Program Files (x86)\Microsoft Visual Studio 9.0\Visual Studio Tools for Office\PIA\Office11\Microsoft.Office.Interop.Word.dll
                    // if (Extension==".doc") 
                    // {
                    //     iframe_Content.Visible = false;
                    //     iframe_Content.Attributes["src"] = "";
                    //     Literal_Content.Visible = true;
                    //     Literal_Content.Text = "";
                    //     Literal_Content.Text = readFileContent(MyState.RootDirFullName + MyState.CurrentPathRel);
                    //     Response.End();
                    // }
                    // send word file to client
                    // if (Extension == ".doc")
                    // {
                    //     FileInfo file = new FileInfo(MyState.RootDirFullName + MyState.CurrentPathRel);
                    //     Response.ClearContent();
                    //     Response.AddHeader("Content-Disposition", "inline;filename=" + file.Name);
                    //     Response.AddHeader("Content-Length", file.Length.ToString());
                    //     Response.ContentType = "application/msword";
                    //     Response.TransmitFile(file.FullName);
                    //     Response.End();
                    // }
                    MyState.CurrentFile = new FileInfo(MyState.CurrentPathAbs).Name.ToLower();
                    FileTypeInfo fti = FileTypes.Get(Extension.ToLower());
                    if (fti != null)
                    {
                        MyState.CurrentIcon = fti.Icon;
                        MyState.CurrentBrush = fti.brush;
                        MyState.CurrentType = fti.Type;
                        MyState.CurrentTemplate = fti.MediaTemplateId;
                    }
                    List<string> m_list = new List<string>();
                    FileGroup ea = null;
                    if (fti == null)
                    {
                        m_list.Add("FilePermissions");
                        m_list.Add("FileHex");
                        m_list.Add("FileDownload");
                    }
                    else
                    {
                        ea = FileGroups.Get(FileTypes.Get(Extension).Type);
                        if (ea.ShowCode) m_list.Add("FileCode");
                        if (ea.ShowFrame && !(MyState.CurrentFile == MyState.OwnFile)) m_list.Add("FileFrame");
                        if (ea.ShowFrame) m_list.Add("FileNewWin");
                        if (ea.ShowDownload) m_list.Add("FileDownload");
                        if (ea.ShowEmbedded) m_list.Add("FileEmbed");
                        if (ea.ShowHex) m_list.Add("FileHex");
                        if (ea.ShowInline) m_list.Add("FileInline");
                        if (ea.ShowPermissions) m_list.Add("FilePermissions");
                        if (ea.ShowSpecial) m_list.Add("FileSpecial");
                        if (ea.ShowExif) m_list.Add("FileExif");
                    }
                    Menu_File.Visible = true;
                    Menu_File.Items.Clear();
                    for (int i = 0; i < Menu_File_Template.Items.Count; i++)
                    {
                        MenuItem mi_template = Menu_File_Template.Items[i];
                        MenuItem mi = new MenuItem(mi_template.Text, mi_template.Value);
                        mi.ToolTip = mi_template.ToolTip;
                        if (IsAllowedMenuItem(mi, m_list))
                            Menu_File.Items.Add(mi);
                    }
                    if (ea != null)
                        if (ea.ShowEmbedded)
                        {
                            DropDownList_Template.Visible = true;
                            DropDownList_Template.Items.Clear();
                            MediaTemplates.list.Sort(MediaTemplate.CompareTemplates);
                            for (int i = 0; i < MediaTemplates.list.Count; i++)
                            {
                                int MediaTemplateId = MediaTemplates.list[i].Id;
                                if
                                    (
                                        ((MyState.CurrentType == FileGroup.Type.AUDIO || MyState.CurrentType == FileGroup.Type.AUDVID) && MediaTemplates.list[i].UseWithAudio)
                                        ||
                                        ((MyState.CurrentType == FileGroup.Type.VIDEO || MyState.CurrentType == FileGroup.Type.AUDVID) && MediaTemplates.list[i].UseWithVideo)
                                        ||
                                        ((MyState.CurrentType == FileGroup.Type.IMAGE || MyState.CurrentType == FileGroup.Type.EXIF) && MediaTemplates.list[i].UseWithImage)
                                    )
                                {
                                    ListItem li = new ListItem(MediaTemplates.list[i].Name, MediaTemplateId.ToString());
                                    if (MediaTemplateId == MyState.CurrentTemplate) li.Selected = true;
                                    DropDownList_Template.Items.Add(li);
                                }
                            }
                        }
                    Label_PathItem.Text = GetRelativePathWithoutItem(MyState.CurrentPathRel, MyState.CurrentFile);
                    if (!Label_PathItem.Text.EndsWith("/")) Label_PathItem.Text += "/";
                    Label_PathItem.ToolTip = Label_PathItem.Text;
                    Label_TitleItem.Text = MyState.CurrentFile;
                    Label_TitleItem.ToolTip = Label_TitleItem.Text;
                    string MimeType = Mime.GetMimeType(Extension); if (string.IsNullOrEmpty(MimeType)) MimeType = "";
                    MimeType = MimeType == "" ? " (-)" : " (" + MimeType + ")";
                    MenuFileExecute(ea == null ? E_ObjectCommand.HEX : ea.ShowFirst);
                    break;
            }
            Page_Load(null, null);
        }
        protected void Tree_Controls_SelectedNodeChanged(object sender, EventArgs e)
        {
            TreeView m = (TreeView)sender;
            TreeNode tn = m.SelectedNode;
            if (MyState.AutocloseTree)
            {
                Tree_Controls.CollapseAll();
                Tree_Content.CollapseAll();
                Tree.ExpandPath(tn);
            }
            if (Tree_Content.SelectedNode != null) Tree_Content.SelectedNode.Selected = false;
            string SelectedValue = m.SelectedValue;
            iframe_Content.Attributes["src"] = "";
            iframe_Content.Visible = false;
            Literal_Content.Visible = false;
            Menu_File.Visible = false;
            Menu_Directory.Visible = false;
            Panel_LoginCommands.Visible = false;
            DropDownList_Template.Visible = false;
            switch (SelectedValue)
            {
                // Server Commands
                case "Server.Variables":
                    // string HelpText = "<span class='HexCaption'>VALUE = Request.ServerVariables[\"PARAMETER\"];</span>\r\n"
                    //     + "<span class='HexTitle'>string PathInfo = Request.ServerVariables[\"PATH_INFO\"];</span>";
                    // Div_ContentItem.Controls.Add(new LiteralControl("<pre>" + HelpText + "</pre>"));
                    Div_ContentItem.Controls.Add((new ListServerVariables(MyState)).GetData());
                    break;
                case "Server.Request":
                    Div_ContentItem.Controls.Add((new ListRequest(MyState)).GetData());
                    break;
                case "Server.Response":
                    Div_ContentItem.Controls.Add((new ListResponse(MyState)).GetData());
                    break;
                case "Server.Server":
                    Div_ContentItem.Controls.Add((new ListServer(MyState)).GetData());
                    break;
                case "Server.Application":
                    Div_ContentItem.Controls.Add((new ListApplication(MyState)).GetData());
                    break;
                case "Server.Session":
                    Div_ContentItem.Controls.Add((new ListSession(MyState)).GetData());
                    break;
                case "Server.MimeExtensions":
                    Div_ContentItem.Controls.Add((new ListMimeByExtension(MyState)).GetData());
                    break;
                case "Server.MimeTypes":
                    Div_ContentItem.Controls.Add((new ListMimeByType(MyState)).GetData());
                    break;
                case "Server.Browser":
                    Div_ContentItem.Controls.Add((new ListBrowser(MyState)).GetData());
                    break;
                case "Server.Mobile":
                    Div_ContentItem.Controls.Add((new ListMobile(MyState)).GetData());
                    break;
                case "Server.Cookies":
                    Div_ContentItem.Controls.Add((new ListCookies(MyState)).GetData());
                    break;
                case "Server.Modules":
                    Div_ContentItem.Controls.Add((new ListModules(MyState)).GetData());
                    break;
                case "Server.Context":
                    Div_ContentItem.Controls.Add((new ListContext(MyState)).GetData());
                    break;
                case "Server.ViewState":
                    Div_ContentItem.Controls.Add((new ListViewState(MyState, ViewState)).GetDataSorted());
                    break;
                case "Server.Environment":
                    Div_ContentItem.Controls.Add((new ListEnvironment(MyState)).GetData());
                    break;
                case "Server.Configuration":
                    Div_ContentItem.Controls.Add((new ListConfiguration(MyState)).GetData());
                    break;
                // Explorer
                case "Explorer.Exif":
                    Div_ContentItem.Controls.Add((new ListExifAll(MyState)).GetData());
                    break;
                case "Explorer.ImageFlags":
                    Div_ContentItem.Controls.Add((new ListImage(MyState)).GetData());
                    break;
                case "Explorer.FileGroups":
                    Div_ContentItem.Controls.Add((new ListFileGroups(MyState)).GetDataSorted());
                    break;
                case "Explorer.Extensions":
                    Div_ContentItem.Controls.Add((new ListExtensions(MyState)).GetDataSorted());
                    break;
                case "Explorer.Templates":
                    Div_ContentItem.Controls.Add((new ListTemplates(MyState)).GetData());
                    break;
                case "Explorer.Attributes":
                    Div_ContentItem.Controls.Add((new ListAttributes(MyState)).GetData());
                    break;
                case "About":
                    Div_ContentItem.Controls.Add((new ListAbout(MyState)).GetData());
                    break;
            }
            MyState.SaveState(ViewState);
        }
    }
}